package ferp.core.ai.strategy.simple;

import com.google.gson2.Gson;
import ferp.center.network.RequestBidAdd;
import ferp.core.ai.nn.Adaptation;
import ferp.core.ai.nn.nen.Nen;
import ferp.core.ai.strategy.Bidding;
import ferp.core.game.Bid;
import ferp.core.game.Game;
import ferp.core.game.Settings;
import ferp.core.log.Log;
import ferp.core.player.Player;

/**
* User: igorgok
* Date: 5/30/11 12:58 PM
*/
public class SimpleBidding extends Bidding
{
  public static void init(Gson gson, String nnj)
  {
    synchronized (lock)
    {
      nn = (nnj == null ? null : Adaptation.createBidNN(gson, nnj));
    }
  }

  @Override
  public Bid bid(Game g, Settings settings, Player ai, Bid min)
  {
    // we will first try to figure out if we can bid misere, then if we can play it
    if (Estimate.misereHand(g.getHand(ai.id()).current) == 0)
      return Bid.misere();

    // find out what table would suggest
    Bid tb = tricks(g, ai);

    // try to use NN
    synchronized (lock)
    {
      if (nn != null)
      {
        float[] input = Adaptation.bid2nni(g.getHand(ai.id()).initial, g.hand, g.getStartingTricks(settings), Adaptation.getLastBid(g.hand, g.bid), Adaptation.getPenalty(g, settings));
        float[] result = nn.get(input);

        // we only care if we need to play
        if (Adaptation.getResult(result[0]) == RequestBidAdd.PLAY)
        {
          Log.debug(Log.TAG, "NN suggests PLAY, min bid is [" + min + "], table bid is [" + tb + "]");

          // check for risk
          if (min.greater(tb))
          {
            final int[] deltas = {2, 2, 1, 0, 0};

            Log.debug(Log.TAG, "allowed delta for " + min.tricks + " is " + deltas[min.tricks - 6] + ", actual " + (min.tricks - tb.tricks));

            if (min.tricks - tb.tricks <= deltas[min.tricks - 6])
              return Bid.play(min.trump, min.tricks);
          }
        }
        else
          Log.debug(Log.TAG, "NN suggests PASS, trying table method...");
      }
    }

    // return the table suggestion
    return tb;
  }

  @Override
  public boolean risk(Game g, Player player, Bid bid)
  {
    // we get here when our bid sucks
    // obviously there is no need to bid if someone already did in such situation
    // that our bid is just 1 trick below the currently allowed bid in the game which is
    // in case no previous bid equals to the starting bid and it's trump is always SPADES
    return g.player.declarer == Game.NO_ID && bid.tricks >= g.options.bid.tricks - 1;
  }

  private static final Object lock = new Object();
  private static Nen nn;

  // estimate max bid for tricks game
  private Bid tricks(Game g, Player player) {return Estimate.tricks(g.getHand(player.id()).current, player.isStarting(g));}
}
